package com.starsoft.trade.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.starsoft.frame.util.DateUtil;
import com.starsoft.smdc.bean.SmdcMarketDaily;
import com.starsoft.smdc.service.SecurityService;
import com.starsoft.trade.bean.TradeBill;
import com.starsoft.trade.bean.TradePosition;
import com.starsoft.trade.bean.TradePositionId;
import com.starsoft.trade.dao.TradePositionDao;
import com.starsoft.trade.util.TradeType;


@Service
public class TradePositionService {

	private static Logger logger = LoggerFactory.getLogger(TradePositionService.class);

	@Autowired
	TradePositionDao positionDao;
	
	@Autowired
	SecurityService securityService;
	
	public TradePosition billToPostion(TradeBill bill, SmdcMarketDaily marketDaily) {
		if (TradeType.get(bill) == TradeType.transfer || TradeType.get(bill) == TradeType.oci) {
			return null;
		}

		Date asof = marketDaily.getId().getTradeDate();
		TradePositionId positionId = new TradePositionId(bill.getAcountId(), asof, bill.getSecId());
		TradePosition position = new TradePosition(positionId);
		if(TradeType.get(bill).isDiv()){
			double interest = securityService.getBondInterset(bill.getSecId(), bill.getBillTime());
			double secValue = (marketDaily.getClosePrice() + interest) * bill.getSecNum();
			position.setSecNum(bill.getSecNum());
			position.setSecValue(secValue);
			position.setTotalCost(-bill.getBillMoney());
			position.setSecNumAfs(Math.min(0, bill.getSecNum()));
			position.setProfitDayMoney(bill.getBillMoney());
		} else {
			double interest = securityService.getBondInterset(bill.getSecId(), bill.getBillTime());
			double secValue = (marketDaily.getClosePrice() + interest) * bill.getSecNum();
			position.setSecNum(bill.getSecNum());
			position.setSecValue(secValue);
			position.setTotalCost(-bill.getBillMoney());
			position.setSecNumAfs(Math.min(0, bill.getSecNum()));
			if (DateUtil.isSameDay(bill.getBillTime(), asof)) {
				position.setProfitDayMoney(secValue + bill.getBillMoney());
			} else {
				position.setProfitDayMoney(bill.getSecNum() * marketDaily.getPriceChange());
			}
		}
		return position;
	}

	public List<TradePosition> billToPostion(List<TradeBill> bills, Map<String, SmdcMarketDaily> marketMap) {
		List<TradePosition> positions = new ArrayList<TradePosition>(bills.size());
		for (TradeBill bill : bills) {
			TradePosition positon = billToPostion(bill, marketMap.get(bill.getSecId()));
			if (positon != null) {
				positions.add(positon);
			}
		}
		return positions;
	}
	
	public List<TradePosition> copyToOtherDay(List<TradePosition> oldPositions, Date asof, Map<String, SmdcMarketDaily> marketMap){
		List<TradePosition> positions = new ArrayList<>();
		for (TradePosition oldPosition : oldPositions) {
			if (oldPosition.getSecNum() == 0) {
				continue;
			}
			String secId = oldPosition.getId().getSecId();
			Integer acountId = oldPosition.getId().getAcountId();
			TradePositionId positionId = new TradePositionId(acountId, asof, secId);

			TradePosition position = new TradePosition(positionId);
			position.setSecNum(oldPosition.getSecNum());
			position.setSecNumAfs(oldPosition.getSecNum());

			SmdcMarketDaily marketDaily = marketMap.get(secId);
			double interest = securityService.getBondInterset(secId, asof);
//			double lastInterest = securityService.getBondInterset(secId, oldPosition.getId().getAsofdate());
			double secValue = (marketDaily.getClosePrice() + interest) * oldPosition.getSecNum();
//			double secValueChange = (interest - lastInterest + marketDaily.getPriceChange())* oldPosition.getSecNum();
			double secValueChange = secValue - oldPosition.getSecValue();
			position.setSecValue(secValue);
			position.setTotalCost(oldPosition.getTotalCost());
			position.setProfitDayMoney(secValueChange);
			position.setBuyDate(oldPosition.getBuyDate());
			positions.add(position);
		}
		return positions;
	}
	
	public TradePosition combinePostion(TradePosition posA, TradePosition posB){
		String secIdA = posA.getId().getSecId();
		String secIdB = posB.getId().getSecId();
		Date dateA = posA.getId().getAsofdate();
		Date dateB = posB.getId().getAsofdate();
		if(!secIdA.equals(secIdB)){
			throw new RuntimeException("不是同一个证券");
		}
		if(!DateUtil.isSameDay(dateA, dateB)){
			throw new RuntimeException("不是同一天");
		}
		posA.setSecNum(posA.getSecNum() + posB.getSecNum());
		posA.setSecNumAfs(posA.getSecNumAfs() + posB.getSecNumAfs());
		posA.setSecValue(posA.getSecValue() + posB.getSecValue());
		posA.setTotalCost(posA.getTotalCost() + posB.getTotalCost());
		posA.setProfitDayMoney(posA.getProfitDayMoney() + posB.getProfitDayMoney());
		if(posA.getBuyDate().compareTo(posB.getBuyDate())>0) {
			posA.setBuyDate(posB.getBuyDate());
		}
		return posA;
	}

	public List<TradePosition> combinePostion(List<TradePosition> positions) {
		Map<String, TradePosition> posMap = new HashMap<>();
		for (TradePosition position : positions) {
			String secId = position.getId().getSecId();
			if(position.getBuyDate()==null) {
				position.setBuyDate(position.getId().getAsofdate());
			}
			if (!posMap.containsKey(secId)) {
				posMap.put(secId, position);
			} else {
				TradePosition combinedPosition = combinePostion(posMap.get(secId), position);
				posMap.put(secId, combinedPosition);
			}
		}
		return new ArrayList<TradePosition>(posMap.values());
	}

}
